﻿
/*============== simpleIRC - http://matthias.van-eeghem.com/ ==============*
 *                                                                         *
 *  File: Core.cs                                                          *
 *  Project: IRC.dll                                                       *
 *  Author(s): Matthias Van Eeghem <matthias@van-eeghem.com>               *
 *                                                                         *
 * ========================================================================*
 *                                                                         *
 *  This program is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 *                                                                         *
===========================================================================*/

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace simpleIRC
{
    /// <summary>
    ///  The core class of the simpleIRC, this holds all variables used in the other classes.
    /// </summary>

    public static class Core
    {
        public enum eObjectType
        {
            Channel,
            Server,
            Query
        }

        // This enum holds the constants for the application's Major and Minor
        public enum eApplicationVersion
        {
            Major = 1,
            Minor = 0
        }
        
        /// <summary>
        /// This enum holds all possible connection states
        /// </summary>

        public enum eConnectionStates
        {
            Disconnected,
            Connecting,
            Connected
        }

        // These lists hold the channel and server objects
        public static List<Server> ServerList = new List<Server>();
        public static List<Channel> ChannelList = new List<Channel>();
        public static List<Query> QueryList = new List<Query>();
        public static List<Logger> LoggerList = new List<Logger>();
        private static Task SendPingTask = null;

        /// <summary>
        /// This method starts the SendPing() method on a different thread
        /// </summary>

        public static void Initialise()
        {
            // Initialise the ping task, this will send the PING command to all servers.
            SendPingTask = new Task(() => Core.SendPing());
            SendPingTask.Start();
        }

        /// <summary>
        /// This method loops through all servers and sends the PING command to each and one of them
        /// </summary>

        public static void SendPing()
        {
            // Loop through all the servers
            foreach (Server Server in ServerList)
            {
                if(Server != null)
                {
                    if (Server.ConnectionState == eConnectionStates.Connected)
                    {
                        // Send the ping command
                        Server.SendData("PING :" + Server.Hostname);
                    }
                }
            }

            // Let the ping thread sleep for 15 seconds.
            Thread.Sleep(15000);

            // After the 15 seconds, call the function again.
            SendPing();
        }

        /// <summary>
        /// This method returns the ServerIndex from a server name
        /// </summary>
        /// <param name="serverName">The server name</param>
        /// <returns>The server index or -1 if no valid server was found</returns>

        public static Server GetServerObject(string serverName)
        {
            int TimesLooped = 0;

            // Loop through all the servers.
            foreach(Server Server in ServerList)
            {
                if (Server != null)
                {
                    if (Server.InternalName == serverName)
                        return Server;
                }

                // Increment the times we've looped.
                TimesLooped++;
            }

            return null;
        }

        /// <summary>
        /// This method returns a query index from the queryname and server index
        /// </summary>
        /// <param name="queryName">The name of the query window</param>
        /// <param name="serverIndex">The server index</param>
        /// <returns>The query index</returns>

        public static Query GetQueryObject(string queryName, int serverIndex)
        {
            // Initialise our variables here.
            int TimesLooped = 0;

            // Loop through all the queries.
            foreach (Query Query in QueryList)
            {
                if (Query != null)
                {
                    if (Query.Name == queryName && serverIndex == Query.Server.Index)
                        return Query;
                }

                // Nothing found, just increase the variable.
                TimesLooped++;
            }

            return null;
        }

        /// <summary>
        /// This method returns a channel object from the channelname and server index
        /// </summary>
        /// <param name="channelName">The name of the channel</param>
        /// <param name="serverIndex">The server index</param>
        /// <returns>The channel object</returns>

        public static Channel GetChannelObject(string channelName, int serverIndex)
        {
            // Initialise our variables here.
            int TimesLooped = 0;

            // Loop through all the channels.
            foreach (Channel Channel in ChannelList)
            {
                // Break the loop if the Channel is null
                if (Channel != null)
                {
                    // Otherwise, match the channel name with saved one.
                    if (Channel.Name.ToLower() == channelName.ToLower() && serverIndex == Channel.Server.Index)
                        return Channel;
                }

                // Nothing found, just increase the variable.
                TimesLooped++;
            }

            return null;
        }

        /// <summary>
        /// This method stops the SendPing() Task started in the Initialise() method and cleans up all variables used by this class.
        /// </summary>

        public static void Destruct()
        {
            int ServerCount = Core.ServerList.Count;

            // Properly delete all servers
            for (int i = 0; i < ServerCount; i++)
            {
                if (Core.ServerList[i] != null)
                    Core.ServerList[i].Disconnect(Core.ServerList[i].Nick);
            }

            ServerList = null;
            ChannelList = null;
            QueryList = null;
            LoggerList = null;
        }
    }
}
